package com.m3958.logcollector.datacommons.util;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;

/**
 * 不是太严谨的解决方案，接近于手工操作的辅助类。
 * 
 * @author jianglibo@gmail.com
 *         2015年10月14日
 *
 */
public class Qparser {

    private static CharMatcher cm = CharMatcher.anyOf("=><");

    private static Splitter commaSplitter = Splitter.on(',').omitEmptyStrings().trimResults();
    private static Splitter kpSplitter = Splitter.on(cm).omitEmptyStrings().trimResults().limit(2);

    private static String extractOp(String c, List<String> ss) {
        try {
            return c.substring(ss.get(0).length(), (c.length() - ss.get(1).length()));
        } catch (Exception e) {
            return "";
        }
    }

    private String qstr;

    private Map<String, Qcriteria> qcriterias = Maps.newHashMap();

    public Qparser(String qstr) {
        this.qstr = qstr;
        parse();
    }

    public Qcriteria getQc(String k) {
        return qcriterias.get(k);
    }

//    public static void main(String... args) {
//        String c = "a>=10";
//        List<String> ss = kpSplitter.splitToList(c);
//
//        String op = extractOp(c, ss);
//        System.out.println(ss);
//        System.out.println(op);
//    }

    /**
     * 逗号分隔a=1,b>10
     */
    private void parse() {
        if (Strings.isNullOrEmpty(qstr)) {
            return;
        }
        qcriterias = commaSplitter.splitToList(qstr).stream()//
                .map(kp -> new Qcriteria(kp))//
                .filter(qc -> qc.isParseSuccess())//
                .collect(Collectors.toMap(qc -> qc.getK(), qc -> qc));
    }

    public static enum Qop {
        EQ, GT, LT, EGT, ELT, BTN
    }

    public static class Qcriteria {
        private String k;

        private String v1;
        private String v2;

        private boolean parseSuccess;

        private Qop qop;

        public Qcriteria(String qstr) {
            parse(qstr);
        }

        /**
         * @param qstr
         */
        private void parse(String pair) {
            List<String> ss = kpSplitter.splitToList(pair);
            if (ss.size() == 2) {
                String op = extractOp(pair, ss);
                if (op.isEmpty()) {
                    setParseSuccess(false);
                    return;
                }
                if (Strings.isNullOrEmpty(ss.get(1))) {
                    setParseSuccess(false);
                    return;
                }
                this.setK(ss.get(0));
                this.setV1(ss.get(1));
                this.assignQop(op);
                setParseSuccess(true);
            } else {
                setParseSuccess(false);
            }
        }

        /**
         * @param op
         */
        private void assignQop(String op) {
            switch (op) {
            case "=":
                setQop(Qop.EQ);
                break;
            case ">":
                setQop(Qop.GT);
                break;
            case "<":
                setQop(Qop.LT);
                break;
            case ">=":
            case "=>":
                setQop(Qop.EGT);
                break;
            case "<=":
            case "=<":
                setQop(Qop.ELT);
                break;
            default:
                break;
            }
        }
        
        public long longValue() {
            return Long.parseLong(v1);
        }
        
        public int intValue() {
            return Integer.parseInt(v1);
        }
        
        public String value() {
            return v1;
        }


        public String getK() {
            return k;
        }

        public void setK(String k) {
            this.k = k;
        }

        public Qop getQop() {
            return qop;
        }

        public void setQop(Qop qop) {
            this.qop = qop;
        }

        public boolean isParseSuccess() {
            return parseSuccess;
        }

        public void setParseSuccess(boolean parseSuccess) {
            this.parseSuccess = parseSuccess;
        }

        public String getV1() {
            return v1;
        }

        public void setV1(String v1) {
            this.v1 = v1;
        }

        public String getV2() {
            return v2;
        }

        public void setV2(String v2) {
            this.v2 = v2;
        }
    }
}
